/*
 * © 2024 huayunliufeng保留所有权利, 依据MIT许可证发布。
 * 请勿更改或删除版权声明或此文件头。
 * 此代码是免费软件, 您可以重新分发和/或修改它。
 * 开源是希望它有用, 但不对代码做任何保证。
 * 如有疑问请联系: huayunliufeng@163.com
 */

package io.github.huayunliufeng.dbinfo.dbinfo;

import io.github.huayunliufeng.common.utils.HylfDataUtil;
import io.github.huayunliufeng.common.utils.HylfFunUtil;
import io.github.huayunliufeng.dbinfo.model.TableIndexInfo;
import lombok.extern.slf4j.Slf4j;

import java.sql.Connection;
import java.sql.ResultSet;
import java.util.List;
import java.util.Map;

/**
 * 获取表的索引。
 *
 * @author zhongq
 * @datetime 2024/3/26 17:25
 */
@Slf4j
public class ObtainIndexInfo extends ObtainDbInfo {

    private static Map<Connection, ObtainIndexInfo> obtainIndexInfoMap = null;

    private Map<String, List<TableIndexInfo>> indexInfoMap = null;

    protected ObtainIndexInfo(Connection conn) {
        super(conn);
    }

    public static ObtainIndexInfo build(Connection conn) {
        obtainIndexInfoMap = HylfFunUtil.mapAddValue(obtainIndexInfoMap, conn, () -> new ObtainIndexInfo(conn));
        return obtainIndexInfoMap.get(conn);
    }

    /**
     * 获取表的索引信息
     *
     * @param catalog     目录名称;必须匹配存储在此数据库中的目录名称;”“检索那些没有目录的;null意味着不应该使用目录名称来缩小搜索范围
     * @param schema      模式名称;必须匹配模式名称，因为它存储在数据库中;""检索没有模式的数据;null意味着不应该使用模式名称来缩小搜索范围
     * @param table       表名;必须与存储在数据库中的表名匹配
     * @param unique      当为true时，仅返回唯一值的下标;当为false时，返回索引，不管索引是否唯一
     * @param approximate 当设置为true时，允许结果反映近似或超出数据值;当为false时，要求结果是准确的
     * @return 表的索引信息
     */
    public List<TableIndexInfo> getIndexInfo(String catalog, String schema, String table, boolean unique, boolean approximate) {
        String logFormat = "获取表的索引失败。[catalog = {}, schema = {}, table = {}, unique = {}, approximate = {}]";
        return HylfFunUtil.methodVoidReturnExec(() -> {
            String key = String.join("-", catalog, schema, table);
            indexInfoMap = HylfFunUtil.mapAddValue(indexInfoMap, key, () -> {
                ResultSet resultSet = HylfFunUtil.methodVoidReturnExec(
                        () -> databaseMetaData.getIndexInfo(catalog, schema, table, unique, approximate),
                        logFormat, catalog, schema, table, unique, approximate);
                List<TableIndexInfo> indexInfoList = HylfDataUtil.autoSetValue(resultSet, TableIndexInfo.class);
                HylfFunUtil.autoClose(resultSet);
                return indexInfoList;
            });
            return indexInfoMap.get(key);
        });
    }

    /**
     * 获取表的索引信息
     *
     * @param catalog 目录名称;必须匹配存储在此数据库中的目录名称;”“检索那些没有目录的;null意味着不应该使用目录名称来缩小搜索范围
     * @param schema  模式名称;必须匹配模式名称，因为它存储在数据库中;""检索没有模式的数据;null意味着不应该使用模式名称来缩小搜索范围
     * @param table   表名;必须与存储在数据库中的表名匹配
     * @return 表的索引信息
     */
    public List<TableIndexInfo> getIndexInfo(String catalog, String schema, String table) {
        return getIndexInfo(catalog, schema, table, false, true);
    }

    /**
     * 获取表的索引信息
     *
     * @param table 表名;必须与存储在数据库中的表名匹配
     * @return 表的索引信息
     */
    public List<TableIndexInfo> getIndexInfo(String table) {
        return getIndexInfo(getCatalog(), getSchema(), table, false, true);
    }

    /**
     * 获取表的索引信息
     *
     * @param table       表名;必须与存储在数据库中的表名匹配
     * @param unique      当为true时，仅返回唯一值的下标;当为false时，返回索引，不管索引是否唯一
     * @param approximate 当设置为true时，允许结果反映近似或超出数据值;当为false时，要求结果是准确的
     * @return 表的索引信息
     */
    public List<TableIndexInfo> getIndexInfo(String table, boolean unique, boolean approximate) {
        return getIndexInfo(getCatalog(), getSchema(), table, unique, approximate);
    }

}
